/**
 * 
 */
package edu.pw.treegrid.server.classmodel;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import edu.pw.treegrid.server.query.Node;
import edu.pw.treegrid.server.reportmodel.ReportColumn;
import edu.pw.treegrid.server.service.XMLMarshaller;

/** 
 * @author Piotrek
 */
public abstract class DomainAttribute {

	public static final String ATTRIBUTE_ELEMENT = "attribute";
	public static final String ID_ATTRIBUTE_NAME = "id";
	public static final String NAME_ELEMENT_NAME = "name";
	
	private String id;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract Node buildQueryNode(ReportColumn reportColumn);

	public abstract SimpleAttribute getSimpleAttribute();

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		DomainAttribute other = (DomainAttribute) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
	
	public Element serializeToXML(Document document) {
		Element attributeElement = document.createElement(ATTRIBUTE_ELEMENT);
		
		attributeElement.setAttribute(ID_ATTRIBUTE_NAME, this.id);
		Element name = document.createElement(NAME_ELEMENT_NAME);
		name.setTextContent(this.name);
		attributeElement.appendChild(name);
		
		serializeToXML(document, attributeElement);
		
		return attributeElement;
	}

	abstract protected void serializeToXML(Document document, Element attributeElement);

	public static DomainAttribute newAttribute(Element ae) {
		DomainAttribute da;
		
		if(isDictionaryAttribute(ae)) {
			da = new DictionaryAttribute();
		}
		else if(isReferenceAttribute(ae)) {
			da = new ReferenceAttribute();
		}
		else {
			da = new SimpleAttribute();
		}
		
		da.deserializeFromXML(ae);
		
		return da;
	}

	protected void deserializeFromXML(Element ae) {
		this.id = ae.getAttribute(ID_ATTRIBUTE_NAME);
		this.name = getElementsText(ae, NAME_ELEMENT_NAME);
	}
	
	public void setReferences(XMLMarshaller xmlMarshaller) {
	}
	
	protected Element getFirstElement(Element parent, String childElementName) {
		return (Element)parent.getElementsByTagName(childElementName).item(0);
	}
	
	protected String getElementsText(Element parent, String childName) {
		return getFirstElement(parent, childName).getTextContent();
	}
	
	protected String getAttributeText(Element e, String attributeName) {
		return e.getAttribute(attributeName).toString();
	}

	private static boolean isReferenceAttribute(Element ae) {
		return ae.getElementsByTagName(ReferenceAttribute.REFERENCE_CLASS_ELEMENT).getLength() > 0;
	}

	private static boolean isDictionaryAttribute(Element ae) {
		return ae.getElementsByTagName(DictionaryAttribute.REFERENCE_ATTRIBUTE_ELEMENT).getLength() > 0;
	}
	
	private DomainClass domainClass;

	public DomainClass getDomainClass() {
		return domainClass;
	}

	public void setDomainClass(DomainClass domainClass) {
		this.domainClass = domainClass;
	}

	@Override
	public String toString() {
		return name;
	}

}